package top.suven.base.util.createcode;

import top.suven.base.util.utilize.DateUtil;
import top.suven.base.util.utilize.StringFormat;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.core.annotation.AnnotationUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.*;


public class CreateCode implements java.io.Serializable {

	private static Map<String, Object> dataMap = new HashMap<String, Object>();
	private static  boolean isCache = true;
	private static String data_source ="ResourceDataSource";

	public static void main(String[] args) throws Exception{
		String module = "";
//		List<Class> list = getCreateFile(Class.forName(args[0]));
//	 	for (int i = 0; i <list.size(); i++) {
//	 		createCode(list.get(i), module);
//	 	}
		createCode(Class.forName(args[0]));

	}

	public static void createCodeList(Class clazz,String datasource){
		String module = "";
		data_source = datasource;
		List<Class> list = getCreateFile(clazz);
	 	for (int i = 0; i <list.size(); i++) {
	 		createCode(list.get(i), module);
	 	}
	}
	
	public static List<Class> getCreateFile(Class obj) {
		String packageName = obj.getPackage().getName();
		String packFile = FreemakerUtil.projectPath
				+ packageName.replaceAll("\\.", "/");
		File f = new File(packFile);
		String fileNames[] = f.list();
		List<Class> list = new ArrayList<Class>();
		for (String fileName : fileNames) {
			try {
				if (fileName.lastIndexOf(".") != -1
						&& fileName.lastIndexOf("$") == -1) {
					String prefix = fileName.substring(0,	fileName.lastIndexOf("."));
					String clazz = packageName + "." + prefix;
					Class classes = CreateCode.class.getClassLoader()	.loadClass(clazz);
					list.add(classes);

				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		return list;
	}


	public static void createCode(Class<?> entityClazz,boolean isUserCache) {
		initMap(entityClazz);
		dataMap.put("module", "");
		dataMap.put("newdate", DateUtil.date("yyyy-MM-dd"));
		dataMap.put("dataSource", data_source);
		dataMap.put("dataSourceLower", "dataSource");
		isCache = isUserCache;

		createDaoImpl();
	}
	
	private static String toLowerIndex(String name){
		return Character.toLowerCase(name.charAt(0)) + name.substring(1);
	}
	
	public static void createCode(Class<?> entityClazz) {
		initMap(entityClazz);
		dataMap.put("module", "");
		dataMap.put("newdate", DateUtil.date("yyyy-MM-dd"));
		dataMap.put("dataSource", data_source);
		dataMap.put("dataSourceLower", "dataSource");
		dataMap.put("author", "suven.wang");
		dataMap.put("description", entityClazz.getSimpleName());
		
		createDaoImpl();
	}

	public static void createCode(Class<?> entityClazz,String dataSource,String author,String description) throws Exception{
		if(StringUtils.isBlank(dataSource)){
			throw new Exception("数据源不能为空");
		}
		if(StringUtils.isBlank(author)){
			throw new Exception("类创建的作者不能为空");
		}
		if(StringUtils.isBlank(description)){
			throw new Exception("类描述不能为空");
		}
		initMap(entityClazz);
		dataMap.put("module", "");
		dataMap.put("newdate", DateUtil.date("yyyy-MM-dd HH:mm:ss"));
		dataMap.put("dataSource", dataSource);
		dataMap.put("dataSourceLower", "dataSource");
		dataMap.put("author", author);
		dataMap.put("description", description);
		createDaoImpl();
	}

	public static void createCode(Class<?> entityClazz, String data_source) {
		initMap(entityClazz);
		dataMap.put("module", data_source);
		dataMap.put("newdate", DateUtil.date("yyyy-MM-dd"));
		dataMap.put("dataSource", data_source);
		dataMap.put("dataSourceLower", "dataSource");
		  
		createDaoImpl();
	}

	public static void initMap(Class<?> entityClazz) {
		dataMap.clear();
		dataMap.put("ctx", "${ctx}");
		dataMap.put("id", "${id}");
		Set<String> setFileName = new HashSet<>();

		// 获取报名(去掉entity),实现类
		String packageName = entityClazz.getPackage().getName();
		if (packageName.endsWith("model")) {
			packageName = packageName.substring(0,
					packageName.indexOf("model") - 1);

		}
		String tableName =  StringFormat.underscoreName(entityClazz.getSimpleName());
		String className = entityClazz.getSimpleName();
		String tableId = "id";
		TableBean tableBean = new TableBean();
		tableBean.setId(tableId)
				.setTableName(tableName)
				.setPackageName(packageName)
				.setClassName(className)
				.setClassLowerCaseName(className.toLowerCase())
				.setClassUpperCaseName(className.toUpperCase())
				.setParamName(toLowerIndex(className))
				.setInsertDbList("List<Object> dbList = new ArrayList<>();")
				.setUpdateDbList("List<Object> dbList = new ArrayList<>();")
				;

		// 将驼峰类名中的大写字母转换为_加字母
		String paramName = tableBean.getParamName();
		String result = "";
		result = StringFormat.underscoreName(paramName);
		dataMap.put("requestPath", result.toLowerCase());


		List<Field> fieldList = FieldUtils.getAllFieldsList(entityClazz);


		Table table = AnnotationUtils.findAnnotation(entityClazz, Table.class);
		if(table != null){
			tableName = table.name();
			if("postgresql".equals(table.sqlType())){
//				columnVal.append("nextval('seq_"+tableName+"'), ");
			}
			tableId = table.columnValue();
		}

		for (Field f : fieldList) {
			Column column = new Column();
			column.setTableName( tableName);
			column.setClassName(tableBean.getClassName());
			column.setFieldName(f.getName());
			column.setType(f.getType().getSimpleName());
			
			if(setFileName.contains(f.getName())){
				continue;
			}
			if(null != table && f.getName().equals(table.columnKey()) ){
				dataMap.put(table.columnKey(),table.columnValue());
				column.setDbName(StringFormat.underscoreName(table.columnValue()));

			}
			setFileName.add(f.getName());

			//查询
			tableBean.setSelectSQL(column.getDbName()).setSelectSQL(", ");
			tableBean.setResultVo(column.getDbFileName());

			//设置更新条件
			if (tableId.equalsIgnoreCase(column.getDbName())) {
				tableBean.setUpdateWhereDbList("\n\t\tdbList.add(")
						.setUpdateWhereDbList(column.getGetFileName())
						.setUpdateWhereDbList(");");
				continue;
			}

			//insert 插入
			tableBean.setInsertSQL(column.getDbName()).setInsertSQL(", ");
			tableBean.setInsertVal("?, ");
			tableBean.setInsertDbList("\n\t\tdbList.add(").setInsertDbList(column.getGetFileName()).setInsertDbList(");");

			//update
			if(!("create_time".equals(column.getDbName() )|| "create_date".equals(column.getDbName() ))){
				tableBean.setUpdateSQL(column.getDbName() + " = ?,");
				tableBean.setUpdateDbList("\n\t\tdbList.add(").setUpdateDbList(column.getGetFileName()).setUpdateDbList(");");
			}

			tableBean.setServiceVo("\n \t\t\t")
					.setServiceVo(column.getSetFileName())
					.setServiceVo(";");
			


		}

		dataMap.put("className",tableBean.getClassName());
		dataMap.put("paramName",tableBean.getParamName());
		dataMap.put("classLowerCaseName",tableBean.getClassLowerCaseName());
		dataMap.put("classUpperCaseName",tableBean.getClassUpperCaseName());
		dataMap.put("tableName",tableBean.getTableName());
		dataMap.put("id",tableBean.getId());
		dataMap.put("dbList", "dbList.toArray()");//传参数组;

		dataMap.put("insertSQL", tableBean.getInsertSQL());//
		dataMap.put("insertVal", tableBean.getInsertVal());//
		dataMap.put("insertDbList", tableBean.getInsertDbList());//

		dataMap.put("updateSQL", tableBean.getUpdateSQL());
		dataMap.put("updateDbList", tableBean.getUpdateDbList());
		dataMap.put("updateWhereDbList", tableBean.getUpdateWhereDbList());

		dataMap.put("selectSQL", tableBean.getSelectSQL());
		dataMap.put("resultVo", tableBean.getResultVo());

		dataMap.put("packageName", packageName);


		dataMap.put("serviceVo", "/**"+tableBean.getServiceVo()+"\n\t\t**/");

		for (String key : dataMap.keySet()) {
			System.out.println(key + "==" + dataMap.get(key));
		}

	}

	public static void createDaoImpl() {
		String outCacheFileName = FreemakerUtil.targerPath
				+ (dataMap.get("packageName") + "").replaceAll("\\.", "/")
				+ EnumsTable.CACHE.getValue() + dataMap.get("className") + "Cache.java";
		
		String outDaoFileName = FreemakerUtil.targerPath
				+ (dataMap.get("packageName") + "").replaceAll("\\.", "/")
				+ EnumsTable.DAO.getValue() + dataMap.get("className") + "Dao.java";
		
		String outServerFileName = FreemakerUtil.targerPath
				+ (dataMap.get("packageName") + "").replaceAll("\\.", "/")
				+ EnumsTable.SERVICE.getValue() + dataMap.get("className") + "Service.java";
		
//		String outControllerFileName = FreemakerUtil.targerPath
//				+ (dataMap.get("packageName") + "").replaceAll("\\.", "/")
//				+ EnumsTable.CONTROLLER + dataMap.get("name") + "Controller.java";

		FreemakerUtil.writeTemp(dataMap, "code_cache_impl.jsp", outCacheFileName);
		if(isCache) {
			FreemakerUtil.writeTemp(dataMap, "code_dao_impl.jsp", outDaoFileName);
			//FreemakerUtil.writeTemp(dataMap, "code_service_impl.jsp", outServerFileName);
		}else {
			FreemakerUtil.writeTemp(dataMap, "code_dao_not_cache_impl.jsp", outDaoFileName);
			//FreemakerUtil.writeTemp(dataMap, "code_service_not_cache_impl.jsp", outServerFileName);
		}
//		FreemakerUtil.writeTemp(dataMap, "code_controller_impl.jsp", outControllerFileName);
	}

}
